package lee.vioson.ebook.viewmodels

import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
import lee.vioson.composecommon.base.mvi.Reducer
import lee.vioson.composecommon.base.mvi.UiEvent
import lee.vioson.composecommon.base.mvi.UiState
import lee.vioson.ebook.data.AppContainer

/**
 *Author:viosonlee
 *Date:2023/6/14
 *DESCRIPTION:
 */
class BookDetailViewModel(private val appContainer: AppContainer, private val bookId: String) :
    AppViewModel<BookDetailViewModel.State, BookDetailViewModel.Event>(appContainer.appEvent) {

    private val reducer = SubReducer(State())

    override val state: StateFlow<State>
        get() = reducer.state

    override fun sendEvent(event: Event) {
        reducer.sendEvent(event)
    }

    fun addCollection(addFavorite: Boolean) =
        appContainer.bookRepository.changeCollection(appContainer.uniqueId, addFavorite, bookId)
            .catch {
                handleException(it)
                sendEvent(Event.OnCollectionLoadingChange(false))
            }
            .onStart { sendEvent(Event.OnCollectionLoadingChange(true)) }
            .onCompletion { sendEvent(Event.OnCollectionLoadingChange(false)) }
            .onEach { if (it) sendEvent(Event.OnCollectionChange(isCollection = addFavorite)) }
            .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), false)
            .launchIn(viewModelScope)

    val bookInfo = appContainer.bookRepository.fetchBookDetail(appContainer.uniqueId, bookId)
        .catch { handleException(it) }
        .onStart { showLoading() }
        .onCompletion { dismissLoading() }
        .onEach {
            it.bookInfo.isCollection = it.isCollection
            sendEvent(Event.OnCollectionChange(it.isCollection))
        }
        .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), null)

    fun markView() = appContainer.bookRepository.markBookView(appContainer.uniqueId, bookId)
        .catch { handleException(it) }
        .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), 0)
        .launchIn(viewModelScope)

    private class SubReducer(initialState: State) :
        Reducer<State, Event>(initialState) {
        override fun reduce(oldState: State, event: Event) {
            when (event) {
                is Event.OnCollectionChange -> setState(oldState.copy(isCollection = event.isCollection))
                is Event.OnCollectionLoadingChange -> setState(oldState.copy(collectionLoading = event.collectionLoading))
            }
        }
    }


    sealed class Event : UiEvent {
        data class OnCollectionChange(val isCollection: Boolean) : Event()
        data class OnCollectionLoadingChange(val collectionLoading: Boolean) : Event()
    }

    data class State(
        val isVip: Boolean = false,
        val isCollection: Boolean = false,
        val collectionLoading: Boolean = false
    ) : UiState
}

